package com.example.petplanet.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.example.petplanet.config.AliyunConfig;
import com.example.petplanet.config.AppConfig;
import com.example.petplanet.domain.User;
import com.example.petplanet.mapper.LikeContentDao;
import com.example.petplanet.mapper.MarkBookDao;
import com.example.petplanet.mapper.RelationDao;
import com.example.petplanet.mapper.UserDao;
import com.example.petplanet.result.Result;
import com.example.petplanet.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class UserService {

    private final UserDao userDao;
    private final AliyunConfig aliyunConfig;
    private final CACHEUtil cacheUtil;
    private final AppConfig appConfig;
    private final RelationDao relationDao;
    private final MarkBookDao markBookDao;
    private final LikeContentDao likeContentDao;
    private final ShareService shareService;


    // 定义 Random 实例为类成员变量
    private final Random random = new Random();


    @Autowired
    UserService(UserDao userDao, AliyunConfig aliyunConfig, CACHEUtil cacheUtil, AppConfig appConfig, RelationDao relationDao, MarkBookDao markBookDao, LikeContentDao likeContentDao, ShareService shareService){
        this.userDao=userDao;
        this.aliyunConfig=aliyunConfig;
        this.cacheUtil=cacheUtil;
        this.appConfig=appConfig;
        this.relationDao=relationDao;
        this.markBookDao = markBookDao;
        this.likeContentDao = likeContentDao;
        this.shareService = shareService;
    }

    public User UserInit(String phone){
        User user=new User();
        user.setPhone(phone);
        if (userDao.Register(user)==0) return null;
        user.setFollows(new HashSet<>());
        user.setFans(new HashSet<>());
        user.setUserTotalBookmarkCount(0L);
        user.setMarkBooks(new HashSet());
        user.setLikeComments(new HashSet<>());
        user.setLikeContents(new HashSet<>());
        user.setUserLikes(0L);
        return user;
    }


    public Result<Object> LoginByPhone(String phone, String code) {
        if(!verifyCode(phone,code)) return Result.error("验证失败");
        User user=userDao.getUserByPhone(phone);
        if (user==null) user=UserInit(phone);
        //获收藏总数
        user.setUserTotalBookmarkCount(markBookDao.getMarkCountByUserId(user.getUserId()));
        //获取被赞总数
        user.setUserLikes(likeContentDao.getLikesByUserId(user.getUserId()));
        String key="app:user:"+user.getUserId().toString();
        String token = null;
        // 创建一个哈希表的值
        Map<String, Object> userData = new HashMap<>();
        String userJson = JSON.toJSONString(user);
        userData.put("user", userJson);
        try {
            //加密userid，生成token，已登录的token缓存在redis，给前端返回token
            String encryptedData= SecureEncryptionUtil.encrypt(user.getUserId().toString(),appConfig.getAppid(),appConfig.getSecret());
            token = JWTUtil.generateToken(encryptedData,appConfig.getJwtTime(),appConfig.getJwtSecret());
            userData.put("token", token);
            cacheUtil.setHash(key,userData,10L, TimeUnit.DAYS);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(token==null) return Result.error("token生成失败");
        return Result.success(token);
    }

    public boolean verifyCode(String phone, String code) {
        String phoneKey="app:phone:"+phone;
        String sessionCode = cacheUtil.getValueStr(phoneKey);
        return sessionCode!=null && sessionCode.equals(code);
        //测试阶段验证码的验证可以先默认都为真
//        return true;
    }

    //用户登出，点赞同步未测试
    public Result<Object> LoginOut(){
        Long userId=TLUtil.getUserId();
        String key="app:user:"+userId.toString();
        User user = shareService.getUserByIdRedis(userId);
        //删除已删除帖子的收藏记录
        if(!shareService.getToDeleteMarkBookIds().isEmpty()) {
            user.getMarkBooks().removeAll(shareService.getToDeleteMarkBookIds());
//            shareService.emptyToDeleteMarkBookIds();
        }
        //退出登录直接同步
        shareService.syncUserFollow(user);
        //确保删除操作不会影响，如果DeleteMarkBookIds还未更新
        shareService.syncUserMarkBook(user);
        //同步点赞，还未测试
        shareService.syncUserLike(userId);
        if (cacheUtil.delete(key))return Result.success();
        return Result.error();
    }

    public Result<Object> getBasicMessage() {
        return Result.success(TLUtil.getUser());
    }

    public Result<Object> editBasicMessage(char sex, Integer age, String name) {
        long userId=TLUtil.getUserId();
        if(userDao.editBasicMessage(userId,sex,age,name)==0) return Result.error("更改失败");
        User user=TLUtil.getUser();
        user.setSex(sex);
        user.setAge(age);
        user.setName(name);
        String key="app:user:"+userId;
        String userJson=JSON.toJSONString(user);
        cacheUtil.updateValueHash(key,"user",userJson,10L,TimeUnit.DAYS);
        return Result.success();
    }


    @Transactional
    public Result<Object> uploadAvatar(MultipartFile file) {
        String fullUrl;
        Long userId = TLUtil.getUserId();
        User user=TLUtil.getUser();
        try {
            fullUrl= OSSUtil.uploadFileToAli("Avatar",".jpg",userId.toString(),"9o9o",userId,file.getInputStream(),aliyunConfig);
        }
        catch (Exception e){
            e.printStackTrace();
            return Result.error("上传失败");
        }
        URL url= null;
        try {
            url = new URL(fullUrl);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        if(url == null) return  Result.error("上传失败");
        String lastUrl=url.getProtocol() + "://" + url.getHost() + url.getPath();
        if(userDao.updateUserAvatar(user.getUserId(),lastUrl) == 0) return Result.error("上传失败");
        user.setAvatar(lastUrl);
        shareService.updateUserRedis(user);
        return Result.success(lastUrl);
    }

    public Result<Object> stsToken() {
        Long userId= TLUtil.getUserId();
        JSONObject ob;
        try {
            ob= STSUtil.getCredit(userId,"first", aliyunConfig);
        }
        catch (Exception e){
            e.printStackTrace();
            return Result.error();
        }
        return Result.success(ob);
    }


    public Result<Object> followUser(Long targetUserId) {
        //自己不可关注
        Long userId = TLUtil.getUserId();
        if(targetUserId == userId) return Result.error("关注失败");
        //查看是否有这个人
        boolean existsRedis=shareService.judgeUserExistsRedis(targetUserId);
        User targetUser;
        if(!existsRedis){
            targetUser = userDao.getUserById(targetUserId);
            if(targetUser == null) return Result.error("找不到此用户");
        }else {
            targetUser = shareService.getUserByIdRedis(targetUserId);
        }
        //更新关注列表，延时
        User user = TLUtil.getUser();
        boolean addition = user.getFollows().add(targetUserId);
        if(!addition) return Result.error("已关注");
        shareService.updateUserRedis(user);
        String key="app:user:"+userId.toString();
        cacheUtil.expire(key,10L,TimeUnit.DAYS);
        //更新粉丝列表
        //用户未登录，直接修改MYSQL数据库
        if(!existsRedis){
            if(relationDao.followUser(userId,targetUserId) == 0) return Result.error("关注失败，请勿重复关注");
            return Result.success();
        }
        targetUser.getFans().add(userId);
        shareService.updateUserRedis(targetUser);
        return Result.success();
    }


    public Result<Object> cancelFollow(Long targetUserId) {
        //自己不可关注
        Long userId = TLUtil.getUserId();
        if(targetUserId == userId) return Result.error("取消关注失败");
        //查看是否有这个人
        boolean existsRedis=shareService.judgeUserExistsRedis(targetUserId);
        User targetUser;
        if(!existsRedis){
            targetUser = userDao.getUserById(targetUserId);
            if(targetUser == null) return Result.error("找不到此用户");
        }else {
            targetUser = shareService.getUserByIdRedis(targetUserId);
        }
        //更新关注列表，延时
        User user = TLUtil.getUser();
        boolean remove = user.getFollows().remove(targetUserId);
        if(!remove) return Result.error("未关注");
        shareService.updateUserRedis(user);
        String key="app:user:"+userId.toString();
        cacheUtil.expire(key,10L,TimeUnit.DAYS);
        //更新粉丝列表
        //用户未登录，直接修改MYSQL数据库
        if(!existsRedis){
            if(relationDao.cancelFollow(userId,targetUserId) == 0) return Result.error("取消关注失败");
            return Result.success();
        }
        targetUser.getFans().remove(userId);
        shareService.updateUserRedis(targetUser);
        return Result.success();
    }


    public Result<Object> getUserBasicMessage(Long targetUserId) {
        Long userId = TLUtil.getUserId();
        if(userId == targetUserId) return Result.success(TLUtil.getUser());
        User user=shareService.getUserByIdRedis(targetUserId);
        if(user == null) user=userDao.getUserById(targetUserId);
        if(user == null) return Result.error("该用户不存在");
        user.setPhone("");
        return Result.success(user);
    }


    public Result<Object> verifyOldPhone(String code) {
        String oldPhone = TLUtil.getUser().getPhone();
        if(!verifyCode(oldPhone,code)) return Result.error("验证失败");
        return Result.success();
    }

    @Transactional
    public Result<Object> changeBind(String phone, String code) {
        if(!verifyCode(phone,code)) return Result.error("验证失败");
        User user=userDao.getUserByPhone(phone);
        if(user!=null) return Result.error("该手机号已被注册");
        if(userDao.updateUserPhone(TLUtil.getUserId(),phone)==0) return Result.error("更改失败");
        TLUtil.getUser().setPhone(phone);
        shareService.updateUserRedis(TLUtil.getUser());
        return Result.success();
    }

    public Result<Object> sendPhoneCode(String phone) {
        String AccessKey=aliyunConfig.getAccessKeyId();
        String AccessSecret=aliyunConfig.getAccessKeySecret();
        //签名模版
        String templateCode="SMS_154950909";
        String signName="阿里云短信测试";
        String code = String.format("%04d", random.nextInt(10000));
        try {
            // 发送短信并获取响应
            SendSmsResponse response = SMSUtil.sendMessage(signName, templateCode, phone, code, AccessKey, AccessSecret);
            if ("OK".equals(response.getCode())) {
                // 存储验证码到Redis
                String phoneKey = "app:phone:" + phone;
                cacheUtil.set(phoneKey,code,120L,TimeUnit.SECONDS);
                return Result.success("验证码已发送，请注意查收");
            } else {
                System.out.println("电话号码："+phone+":发送失败："+response.getMessage());
                return Result.error("短信发送失败：" + response.getMessage());
            }
        } catch (ClientException e) {
            e.printStackTrace();
            System.out.println("电话号码："+phone+":发送异常："+e.getErrMsg());
            return Result.error("短信发送异常：" + e.getErrMsg());
        }
    }

}
